// Top-level actor class
//--------------------------------
#ifndef ACTOR_H
#define ACTOR_H
#include "common.h"
#include "bbasic.h"
#include "bspecial.h"
#include "behaved.h"

class Actor : public Behaved, public BIIsActor,
              public BIName, public BISymbol, public BISpeed, public BIOnSetFire, public BIOnPushed, public BIOnMove {
public:

    Actor();
    virtual ~Actor();

    // Positioning within the game world
    void SetMap( Map* map, uint x, uint y );
    void SetPosition( uint x, uint y );
    virtual const Map* GetMap() const;
    virtual       Map* GetMap();
    int GetX( uint direction = 0 ) const;
    int GetY( uint direction = 0 ) const;

    // Removal - don't delete directly
    virtual void Destroy();
    virtual bool IsDestroyed() const;

    // Priority - affects the order in which actors are displayed
    // to the player
    static bool PrioritySort( const Actor* less, const Actor* greater );

    // Invalidate all held references to this actor
    void InvalidateReferences();
    friend class ActorReference;

    // Helpful functions
    uint DirectionTo( int x, int y );
    void GetAdjacentActors(      ActorList& outputList, uint flammableMask = 0 );
    void GetAdjacentActors( ConstActorList& outputList, uint flammableMask = 0 ) const;
    bool CanBeSeenByPlayer() const;

protected:

    // Behaviours
    virtual bool IsActor( Actor** actor ) const;
    virtual bool Symbol( IO::SymList* list ) const;
    virtual bool Speed( int* speed ) const;
    virtual bool Name( std::string* name, bool* plural, uint article ) const;
    virtual bool OnSetFire();
    virtual bool OnMove( uint* direction, bool* moved );
    virtual bool OnPushed( Actor* source, bool reverse, bool* pushed, bool first );

private:

    // Position within the game world
    uint _x;
    uint _y;
    Map* _map;

    // Basic data
    bool _destroy;

    // References
    typedef std::vector< bool* > RefList;
    RefList _refList;

};

// Allows actors to safely hold references to other actors indefinitely
class ActorReference {
public:

    ActorReference( Actor* a );
    ActorReference( const ActorReference& a );
    ~ActorReference();

    ActorReference& operator=( Actor* a );
    ActorReference& operator=( const ActorReference& a );

    bool operator==( const ActorReference& a ) const;
    bool operator!=( const ActorReference& a ) const;

    bool  IsValid() const;
    operator bool() const;

    const Actor& operator* () const;
          Actor& operator* ();
    const Actor* operator->() const;
          Actor* operator->();

private:

    void Set( Actor* a );
    void Set( const ActorReference& a );
    void Unset();

    Actor* _actor;
    bool   _invalidated;
    
};

#endif
